package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.eastfair.venueservice.dao.ExhibitionCompanyMapper;
import com.eastfair.venueservice.dto.ExhibitionCompanyDTO;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.entity.ExhibitionCompany;
import com.eastfair.venueservice.enumeration.ExhibitionCompanyCompanySourceEnum;
import com.eastfair.venueservice.enumeration.ExhibitionCompanyCompanyTypeEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.ExhibitionCompanyService;
import com.eastfair.venueservice.service.ServiceOrderService;
import com.eastfair.venueservice.vo.ExhibitionCompanyVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 展会相关企业
 * </p>
 *
 * @author dq
 * @date 2022-09-28
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ExhibitionCompanyServiceImpl extends SuperServiceImpl<ExhibitionCompanyMapper, ExhibitionCompany> implements ExhibitionCompanyService {

    private static final String COMPANY_CODE_PREFIX = "BU";

    private static final String COMPANY_CODE_FIELD = "company_code";

    private static final int COMPANY_CODE_LENGTH = 7;

    @Resource
    private ServiceOrderService serviceOrderService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ExhibitionCompany> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ExhibitionCompany model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getIsServiceProvider() == null) {
            model.setIsServiceProvider(BusinessConstant.NO);
        }
        if (model.getIsExhibitor() == null) {
            model.setIsExhibitor(BusinessConstant.NO);
        }
        return R.successDef();
    }

    @Override
    public Page<ExhibitionCompanyVO> listExhibitionCompanyVOs(PageParams<ExhibitionCompanyDTO> pageParams) {
        log.info("listExhibitionCompanyVOs - 分页查询展会企业, pageParams={}", pageParams);
        Page<ExhibitionCompany> page = listExhibitionCompany(pageParams);
        Page<ExhibitionCompanyVO> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        List<ExhibitionCompany> list = page.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<ExhibitionCompanyVO> voList = list
                .stream()
                .map(exhibitionCompany -> {
                    ExhibitionCompanyVO exhibitionCompanyVO = BeanUtil.toBean(exhibitionCompany, ExhibitionCompanyVO.class);
                    // todo 缺违规记录
                    exhibitionCompanyVO.setBadRecordCount(0);
                    return exhibitionCompanyVO;
                })
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public Page<ExhibitionCompany> listExhibitionCompany(PageParams<ExhibitionCompanyDTO> pageParams) {
        log.info("listExhibitionCompany - 分页查询展会企业, pageParams={}", pageParams);
        Page<ExhibitionCompany> pageParam = pageParams.buildPage();
        ExhibitionCompanyDTO model = pageParams.getModel();
        QueryWrapper<ExhibitionCompany> queryWrapper = createExhibitionCompanyQueryWrapper(model);
        return page(pageParam, queryWrapper);
    }

    @Override
    public List<ExhibitionCompany> listExhibitionCompany(ExhibitionCompanyDTO query) {
        log.info("listExhibitionCompany - 查询展会企业列表, exhibitionCompanyDTO={}", query);
        QueryWrapper<ExhibitionCompany> queryWrapper = createExhibitionCompanyQueryWrapper(query);
        return list(queryWrapper);
    }

    @Override
    public List<ExhibitionCompany> listByServiceProviderIds(List<Long> serviceProviderIds, Long exhibitionManageId) {
        ExhibitionCompanyDTO param = new ExhibitionCompanyDTO();
        param.setServiceProviderIdList(serviceProviderIds);
        param.setExhibitionManageId(exhibitionManageId);
        return listExhibitionCompany(param);
    }

    @Override
    public ExhibitionCompanyVO getExhibitionCompanyVOById(Long id) {
        log.info("getExhibitionCompanyVOById - ID获取展会企业详情, id={}", id);
        ExhibitionCompany exhibitionCompany = getById(id);
        if (exhibitionCompany == null) {
            return null;
        }
        return BeanUtil.toBean(exhibitionCompany, ExhibitionCompanyVO.class);
    }

    @Override
    public ExhibitionCompanyVO getVOByServiceProviderId(Long serviceProviderId, Long exhibitionMangeId) {
        log.info("getVOByServiceProviderId - 服务商ID查询展会企业VO, serviceProviderId={}, exhibitionMangeId={}", serviceProviderId, exhibitionMangeId);
        ExhibitionCompany exhibitionCompany = getByServiceProviderId(serviceProviderId, exhibitionMangeId);
        if (exhibitionCompany == null) {
            return null;
        }
        return BeanUtil.toBean(exhibitionCompany, ExhibitionCompanyVO.class);
    }

    @Override
    public ExhibitionCompany getByServiceProviderId(Long serviceProviderId, Long exhibitionMangeId) {
        log.info("getByServiceProviderId - 服务商ID查询展会企业VO, serviceProviderId={}, exhibitionMangeId={}", serviceProviderId, exhibitionMangeId);
        ExhibitionCompanyDTO param = new ExhibitionCompanyDTO();
        param.setServiceProviderId(serviceProviderId);
        param.setExhibitionManageId(exhibitionMangeId);
        List<ExhibitionCompany> list = listExhibitionCompany(param);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public ExhibitionCompany getSponsorByPhone(String phone, Long exhibitionManageId) {
        ExhibitionCompanyDTO query = new ExhibitionCompanyDTO();
        query.setExhibitionManageId(exhibitionManageId);
        query.setEqPhone(phone);
        query.setCompanyType(ExhibitionCompanyCompanyTypeEnum.SPONSOR);
        List<ExhibitionCompany> list = listExhibitionCompany(query);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveExhibitionCompany(ExhibitionCompanyDTO exhibitionCompanyDTO) {
        log.info("saveExhibitionCompany - 保存展会企业, exhibitionCompanyDTO={}", exhibitionCompanyDTO);
        if (ExhibitionCompanyCompanyTypeEnum.SPONSOR.eq(exhibitionCompanyDTO.getCompanyType())) {
            ExhibitionCompany existSponsor = getSponsorByPhone(exhibitionCompanyDTO.getPhone(), exhibitionCompanyDTO.getExhibitionManageId());
            if (existSponsor != null) {
                throw BizException.wrap(VenueServiceExceptionCode.EXHIBITION_COMPANY_SPONSOR_PHONE_EXIST.getCode(), "主办方在该展会手机号已注册，请更换其他手机号");
            }
        }
        if (StrUtil.isBlank(exhibitionCompanyDTO.getCompanyCode())) {
            // 生成企业编码
            String companyCode = CreatCode.creatCode(baseMapper, COMPANY_CODE_FIELD, COMPANY_CODE_LENGTH, COMPANY_CODE_PREFIX);
            exhibitionCompanyDTO.setCompanyCode(companyCode);
        }
        ExhibitionCompany exhibitionCompany = BeanUtil.toBean(exhibitionCompanyDTO, ExhibitionCompany.class);
        return save(exhibitionCompany);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatchExhibitionCompany(List<ExhibitionCompanyDTO> list) {
        log.info("saveBatch - 批量保存, list={}", list);
        if (list == null || list.isEmpty()) {
            return false;
        }
        // 批量保存展会企业
        list.forEach(this::saveExhibitionCompany);
        return true;
    }

    @Override
    public boolean saveBatchByHomeOrMainTransport(List<ServiceProviderVO> serviceProviderList, Long exhibitionManageId) {
        log.info("saveBatchByExhibitionServiceProvider - 展会服务商列表批量保存展会企业, list={}", serviceProviderList);
        if (serviceProviderList == null || serviceProviderList.isEmpty()) {
            return false;
        }
        List<Long> serviceProviderIds = serviceProviderList
                .stream()
                .map(ServiceProviderVO::getId)
                .collect(Collectors.toList());
        // 查询已经存在的展会企业，已经存在的不会新增
        List<ExhibitionCompany> exhibitionCompanyList = listByServiceProviderIds(serviceProviderIds, exhibitionManageId);
        Map<Long, ExhibitionCompany> exhibitionCompanyMap = new HashMap<>(16);
        exhibitionCompanyList
                .forEach(exhibitionCompany -> exhibitionCompanyMap.put(exhibitionCompany.getServiceProviderId(), exhibitionCompany));
        List<ExhibitionCompanyDTO> list = serviceProviderList
                .stream()
                .map(serviceProviderVO -> toExhibitionCompanyDTO(serviceProviderVO, exhibitionManageId))
                .collect(Collectors.toList());
        // 批量保存展会企业
        list.forEach(exhibitionCompanyDTO -> {
            if (!exhibitionCompanyMap.containsKey(exhibitionCompanyDTO.getServiceProviderId())) {
                saveExhibitionCompany(exhibitionCompanyDTO);
            }
        });
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateExhibitionCompany(ExhibitionCompanyDTO exhibitionCompanyDTO) {
        log.info("updateExhibitionCompany - 更新展会企业, exhibitionCompanyDTO={}", exhibitionCompanyDTO);
        if (ExhibitionCompanyCompanyTypeEnum.SPONSOR.eq(exhibitionCompanyDTO.getCompanyType())) {
            ExhibitionCompany existSponsor = getSponsorByPhone(exhibitionCompanyDTO.getPhone(), exhibitionCompanyDTO.getExhibitionManageId());
            if (existSponsor != null && !exhibitionCompanyDTO.getId().equals(existSponsor.getId())) {
                throw BizException.wrap(VenueServiceExceptionCode.EXHIBITION_COMPANY_SPONSOR_PHONE_EXIST.getCode(), "主办方在该展会手机号已注册，请更换其他手机号");
            }
        }
        ExhibitionCompany exhibitionCompany = BeanUtil.toBean(exhibitionCompanyDTO, ExhibitionCompany.class);
        return updateById(exhibitionCompany);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeExhibitionCompanyById(Long id) {
        log.info("removeById - ID删除展会企业, ids={}", id);
        // 校验企业是否有订单
        if (serviceOrderService.existServiceOrderByCompanyId(id)) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_EXIST_CAN_NOT_DELETE.getCode(), "删除失败，企业拥有未取消的订单");
        }
        // 删除展会企业
        ExhibitionCompanyDTO param = new ExhibitionCompanyDTO();
        param.setId(id);
        List<ExhibitionCompany> list = listExhibitionCompany(param);
        return removeByIdsOfLogic(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByServiceProviderId(List<Long> serviceProviderIds, Long exhibitionManageId) {
        log.info("removeByServiceProviderId - 服务商ID，展会ID移除展会企业, serviceProviderId={}, exhibitionManageId={}",
                serviceProviderIds, exhibitionManageId);
        List<ExhibitionCompany> list = listByServiceProviderIds(serviceProviderIds, exhibitionManageId);
        if (list == null || list.isEmpty()) {
            return false;
        }
        return removeByIdsOfLogic(list);
    }

    /**
     * 创建ExhibitionCompany的查询.
     *
     * @param query ExhibitionCompanyDTO.
     * @return QueryWrapper.
     */
    private QueryWrapper<ExhibitionCompany> createExhibitionCompanyQueryWrapper(ExhibitionCompanyDTO query) {
        QueryWrapper<ExhibitionCompany> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ExhibitionCompany::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getId() != null, ExhibitionCompany::getId, query.getId())
                .eq(query.getServiceProviderId() != null,
                        ExhibitionCompany::getServiceProviderId, query.getServiceProviderId())
                .in(query.getServiceProviderIdList() != null && !query.getServiceProviderIdList().isEmpty(),
                        ExhibitionCompany::getServiceProviderId, query.getServiceProviderIdList())
                .eq(query.getExhibitionManageId() != null,
                        ExhibitionCompany::getExhibitionManageId, query.getExhibitionManageId())
                .like(StrUtil.isNotBlank(query.getCompanyName()), ExhibitionCompany::getCompanyName, query.getCompanyName())
                .like(StrUtil.isNotBlank(query.getContact()), ExhibitionCompany::getContact, query.getContact())
                .like(StrUtil.isNotBlank(query.getPhone()), ExhibitionCompany::getPhone, TypeHandlerUtil.crypt(query.getPhone()))
                .eq(query.getCompanyType() != null, ExhibitionCompany::getCompanyType, query.getCompanyType())
                .eq(StrUtil.isNotBlank(query.getEqPhone()), ExhibitionCompany::getPhone, query.getEqPhone())
        ;
        return queryWrapper;
    }

    /**
     * 主场或主运转换为展会企业
     *
     * @param serviceProviderVO  主场或主运服务商
     * @param exhibitionManageId 展会ID
     * @return 展会企业
     */
    private ExhibitionCompanyDTO toExhibitionCompanyDTO(ServiceProviderVO serviceProviderVO, Long exhibitionManageId) {
        ExhibitionCompanyDTO exhibitionCompanyDTO = new ExhibitionCompanyDTO();
        exhibitionCompanyDTO.setCompanyCode(serviceProviderVO.getCompanyCode());
        exhibitionCompanyDTO.setCompanyName(serviceProviderVO.getCompanyName());
        ExhibitionCompanyCompanyTypeEnum exhibitionCompanyCompanyTypeEnum
                = ExhibitionCompanyCompanyTypeEnum.get(serviceProviderVO.getServiceProviderType());
        if (exhibitionCompanyCompanyTypeEnum != null) {
            exhibitionCompanyDTO.setCompanyType(exhibitionCompanyCompanyTypeEnum);
        }
        exhibitionCompanyDTO.setCompanySource(ExhibitionCompanyCompanySourceEnum.SYSTEM_OPERATE);
        exhibitionCompanyDTO.setExhibitionManageId(exhibitionManageId);
        exhibitionCompanyDTO.setIsServiceProvider(BusinessConstant.YES);
        exhibitionCompanyDTO.setServiceProviderId(serviceProviderVO.getId());
        exhibitionCompanyDTO.setServiceProviderName(serviceProviderVO.getCompanyName());
        exhibitionCompanyDTO.setIsExhibitor(BusinessConstant.NO);
        exhibitionCompanyDTO.setContact(serviceProviderVO.getPrincipalName());
        exhibitionCompanyDTO.setPhone(serviceProviderVO.getPrincipalMobile());
        exhibitionCompanyDTO.setHasSite(BusinessConstant.NO);
        return exhibitionCompanyDTO;
    }
}
